﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.MountAndBlade.View.MissionViews.Singleplayer.SiegeDeploymentVisualizationMissionView
// Assembly: TaleWorlds.MountAndBlade.View, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 61152EB8-513B-4D4A-8AC0-0D1465C6CF6C
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\Modules\Native\bin\Win64_Shipping_Client\TaleWorlds.MountAndBlade.View.dll

using System;
using System.Collections.Generic;
using System.Linq;
using TaleWorlds.DotNet;
using TaleWorlds.Engine;
using TaleWorlds.Library;

#nullable disable
namespace TaleWorlds.MountAndBlade.View.MissionViews.Singleplayer
{
  public class SiegeDeploymentVisualizationMissionView : MissionView
  {
    private static int deploymentVisualizerSelector;
    private List<DeploymentPoint> _deploymentPoints;
    private bool _deploymentPointsVisible;
    private Dictionary<DeploymentPoint, List<Vec3>> _deploymentArcs = new Dictionary<DeploymentPoint, List<Vec3>>();
    private Dictionary<DeploymentPoint, (GameEntity, GameEntity)> _deploymentBanners = new Dictionary<DeploymentPoint, (GameEntity, GameEntity)>();
    private Dictionary<DeploymentPoint, GameEntity> _deploymentLights = new Dictionary<DeploymentPoint, GameEntity>();
    private DeploymentMissionView _deploymentMissionView;
    private const uint EntityHighlightColor = 4289622555;

    public override void AfterStart()
    {
      base.AfterStart();
      this._deploymentPoints = Mission.Current.ActiveMissionObjects.FindAllWithType<DeploymentPoint>().Where<DeploymentPoint>((Func<DeploymentPoint, bool>) (dp => !dp.IsDisabled)).ToList<DeploymentPoint>();
      foreach (DeploymentPoint deploymentPoint in this._deploymentPoints)
      {
        deploymentPoint.OnDeploymentPointTypeDetermined += new Action<DeploymentPoint>(this.OnDeploymentPointStateSet);
        deploymentPoint.OnDeploymentStateChanged += new Action<DeploymentPoint, SynchedMissionObject>(this.OnDeploymentStateChanged);
      }
      this._deploymentPointsVisible = true;
      Mission.Current.GetMissionBehavior<SiegeDeploymentMissionController>();
    }

    public override void OnMissionScreenInitialize()
    {
      base.OnMissionScreenInitialize();
      this._deploymentMissionView = this.Mission.GetMissionBehavior<DeploymentMissionView>();
      this._deploymentMissionView.OnDeploymentFinish += new OnPlayerDeploymentFinishDelegate(this.OnDeploymentFinish);
    }

    public void OnDeploymentFinish()
    {
      this._deploymentMissionView.OnDeploymentFinish -= new OnPlayerDeploymentFinishDelegate(this.OnDeploymentFinish);
      this._deploymentMissionView = (DeploymentMissionView) null;
      this.TryRemoveDeploymentVisibilities();
      Mission.Current.RemoveMissionBehavior((MissionBehavior) this);
    }

    protected override void OnEndMission()
    {
      base.OnEndMission();
      this.TryRemoveDeploymentVisibilities();
    }

    public override void OnRemoveBehavior() => base.OnRemoveBehavior();

    private void TryRemoveDeploymentVisibilities()
    {
      if (!this._deploymentPointsVisible)
        return;
      foreach (DeploymentPoint deploymentPoint in this._deploymentPoints)
      {
        this.RemoveDeploymentVisibility(deploymentPoint);
        deploymentPoint.OnDeploymentStateChanged -= new Action<DeploymentPoint, SynchedMissionObject>(this.OnDeploymentStateChanged);
      }
      this._deploymentPointsVisible = false;
    }

    private void RemoveDeploymentVisibility(DeploymentPoint deploymentPoint)
    {
      switch (deploymentPoint.GetDeploymentPointType())
      {
        case DeploymentPoint.DeploymentPointType.BatteringRam:
          this.HideDeploymentBanners(deploymentPoint, true);
          this.SetGhostVisibility(deploymentPoint, false);
          break;
        case DeploymentPoint.DeploymentPointType.TowerLadder:
          this.HideDeploymentBanners(deploymentPoint, true);
          this.SetGhostVisibility(deploymentPoint, false);
          this.SetDeploymentTargetContourState(deploymentPoint, false);
          this.SetLaddersUpState(deploymentPoint, false);
          this.SetLightState(deploymentPoint, false);
          break;
        case DeploymentPoint.DeploymentPointType.Breach:
          this.HideDeploymentBanners(deploymentPoint, true);
          this.SetDeploymentTargetContourState(deploymentPoint, false);
          this.SetLightState(deploymentPoint, false);
          break;
      }
    }

    private static string GetSelectorStateDescription()
    {
      string stateDescription = "";
      for (int index = 1; index < 1023; index *= 2)
      {
        if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & index) > 0)
          stateDescription = stateDescription + " " + ((SiegeDeploymentVisualizationMissionView.DeploymentVisualizationPreference) index).ToString();
      }
      return stateDescription;
    }

    [CommandLineFunctionality.CommandLineArgumentFunction("set_deployment_visualization_selector", "mission")]
    public static string SetDeploymentVisualizationSelector(List<string> strings)
    {
      return strings.Count == 1 && int.TryParse(strings[0], out SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector) ? "Enabled deployment visualization options are:" + SiegeDeploymentVisualizationMissionView.GetSelectorStateDescription() : "Format is \"mission.set_deployment_visualization_selector [integer > 0]\".";
    }

    private void OnDeploymentStateChanged(
      DeploymentPoint deploymentPoint,
      SynchedMissionObject targetObject)
    {
      this.OnDeploymentPointStateSet(deploymentPoint);
    }

    private void OnDeploymentPointStateSet(DeploymentPoint deploymentPoint)
    {
      switch (deploymentPoint.GetDeploymentPointState())
      {
        case DeploymentPoint.DeploymentPointState.NotDeployed:
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 1) > 0)
          {
            if (deploymentPoint.GetDeploymentPointType() != DeploymentPoint.DeploymentPointType.BatteringRam)
              break;
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 2) > 0)
              this.ShowLineFromDeploymentPointToTarget(deploymentPoint);
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 4) > 0)
              this.CreateArcPoints(deploymentPoint);
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 8) > 0)
              this.ShowDeploymentBanners(deploymentPoint);
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 16) > 0)
              this.ShowPath(deploymentPoint);
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 32) <= 0)
              break;
            this.SetGhostVisibility(deploymentPoint, true);
            break;
          }
          if (deploymentPoint.GetDeploymentPointType() != DeploymentPoint.DeploymentPointType.BatteringRam)
            break;
          this.HideDeploymentBanners(deploymentPoint);
          break;
        case DeploymentPoint.DeploymentPointState.BatteringRam:
        case DeploymentPoint.DeploymentPointState.SiegeTower:
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 2) > 0)
            this.ShowLineFromDeploymentPointToTarget(deploymentPoint);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 4) > 0)
            this.CreateArcPoints(deploymentPoint);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 8) > 0)
            this.ShowDeploymentBanners(deploymentPoint);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 16) > 0)
            this.ShowPath(deploymentPoint);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 32) > 0)
            this.SetGhostVisibility(deploymentPoint, true);
          this.SetLaddersUpState(deploymentPoint, false);
          this.SetLightState(deploymentPoint, false);
          break;
        case DeploymentPoint.DeploymentPointState.SiegeLadder:
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 2) > 0)
            this.ShowLineFromDeploymentPointToTarget(deploymentPoint);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 4) > 0)
            this.CreateArcPoints(deploymentPoint);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 8) > 0)
            this.ShowDeploymentBanners(deploymentPoint);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 64) > 0)
            this.SetDeploymentTargetContourState(deploymentPoint, true);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 128) > 0)
            this.SetLaddersUpState(deploymentPoint, true);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 256) <= 0)
            break;
          this.SetLightState(deploymentPoint, true);
          break;
        case DeploymentPoint.DeploymentPointState.Breach:
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 2) > 0)
            this.ShowLineFromDeploymentPointToTarget(deploymentPoint);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 4) > 0)
            this.CreateArcPoints(deploymentPoint);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 8) > 0)
            this.ShowDeploymentBanners(deploymentPoint);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 64) > 0)
            this.SetDeploymentTargetContourState(deploymentPoint, true);
          if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 256) <= 0)
            break;
          this.SetLightState(deploymentPoint, true);
          break;
      }
    }

    public override void OnMissionScreenTick(float dt)
    {
      base.OnMissionScreenTick(dt);
      foreach (DeploymentPoint deploymentPoint in this._deploymentPoints)
      {
        switch (deploymentPoint.GetDeploymentPointState())
        {
          case DeploymentPoint.DeploymentPointState.NotDeployed:
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 1) > 0 && deploymentPoint.GetDeploymentPointType() == DeploymentPoint.DeploymentPointType.BatteringRam)
            {
              if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 2) > 0)
                this.ShowLineFromDeploymentPointToTarget(deploymentPoint);
              if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 4) > 0)
                this.ShowArcFromDeploymentPointToTarget(deploymentPoint);
              if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 16) > 0)
              {
                this.ShowPath(deploymentPoint);
                continue;
              }
              continue;
            }
            continue;
          case DeploymentPoint.DeploymentPointState.BatteringRam:
          case DeploymentPoint.DeploymentPointState.SiegeTower:
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 2) > 0)
              this.ShowLineFromDeploymentPointToTarget(deploymentPoint);
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 4) > 0)
              this.ShowArcFromDeploymentPointToTarget(deploymentPoint);
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 16) > 0)
            {
              this.ShowPath(deploymentPoint);
              continue;
            }
            continue;
          case DeploymentPoint.DeploymentPointState.SiegeLadder:
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 2) > 0)
              this.ShowLineFromDeploymentPointToTarget(deploymentPoint);
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 4) > 0)
            {
              this.ShowArcFromDeploymentPointToTarget(deploymentPoint);
              continue;
            }
            continue;
          case DeploymentPoint.DeploymentPointState.Breach:
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 2) > 0)
              this.ShowLineFromDeploymentPointToTarget(deploymentPoint);
            if ((SiegeDeploymentVisualizationMissionView.deploymentVisualizerSelector & 4) > 0)
            {
              this.ShowArcFromDeploymentPointToTarget(deploymentPoint);
              continue;
            }
            continue;
          default:
            continue;
        }
      }
    }

    private void ShowLineFromDeploymentPointToTarget(DeploymentPoint deploymentPoint)
    {
      deploymentPoint.GetDeploymentOrigin();
      Vec3 deploymentTargetPosition = deploymentPoint.DeploymentTargetPosition;
    }

    private List<Vec3> CreateArcPoints(DeploymentPoint deploymentPoint)
    {
      Vec3 deploymentOrigin = deploymentPoint.GetDeploymentOrigin();
      Vec3 deploymentTargetPosition = deploymentPoint.DeploymentTargetPosition;
      float num1 = (deploymentTargetPosition - deploymentOrigin).Length / 3f;
      List<Vec3> arcPoints = new List<Vec3>();
      for (int index = 0; (double) index < (double) num1; ++index)
      {
        Vec3 vec3 = MBMath.Lerp(deploymentOrigin, deploymentTargetPosition, (float) index / num1, 0.0f);
        float num2 = (float) (8.0 - (double) MathF.Pow(MathF.Abs((float) index - num1 * 0.5f) / (num1 * 0.5f), 1.2f) * 8.0);
        vec3.z += num2;
        arcPoints.Add(vec3);
      }
      arcPoints.Add(deploymentTargetPosition);
      return arcPoints;
    }

    private void ShowArcFromDeploymentPointToTarget(DeploymentPoint deploymentPoint)
    {
      Vec3 deploymentTargetPosition = deploymentPoint.DeploymentTargetPosition;
      List<Vec3> arcPoints;
      this._deploymentArcs.TryGetValue(deploymentPoint, out arcPoints);
      if (arcPoints == null || arcPoints[arcPoints.Count - 1] != deploymentTargetPosition)
        arcPoints = this.CreateArcPoints(deploymentPoint);
      Vec3 vec3_1 = Vec3.Invalid;
      foreach (Vec3 vec3_2 in arcPoints)
      {
        int num = vec3_1.IsValid ? 1 : 0;
        vec3_1 = vec3_2;
      }
    }

    private void ShowDeploymentBanners(DeploymentPoint deploymentPoint)
    {
      Vec3 deploymentOrigin = deploymentPoint.GetDeploymentOrigin();
      Vec3 deploymentTargetPosition = deploymentPoint.DeploymentTargetPosition;
      (GameEntity, GameEntity) tuple;
      this._deploymentBanners.TryGetValue(deploymentPoint, out tuple);
      if ((NativeObject) tuple.Item1 == (NativeObject) null || (NativeObject) tuple.Item2 == (NativeObject) null)
        this.CreateBanners(deploymentPoint);
      GameEntity gameEntity1 = this._deploymentBanners[deploymentPoint].Item1;
      MatrixFrame identity1 = MatrixFrame.Identity with
      {
        origin = deploymentOrigin
      };
      identity1.origin.z += 7.5f;
      identity1.rotation.ApplyScaleLocal(10f);
      MatrixFrame frame1 = identity1;
      gameEntity1.SetFrame(ref frame1);
      gameEntity1.SetVisibilityExcludeParents(true);
      gameEntity1.SetAlpha(1f);
      GameEntity gameEntity2 = this._deploymentBanners[deploymentPoint].Item2;
      MatrixFrame identity2 = MatrixFrame.Identity with
      {
        origin = deploymentTargetPosition
      };
      identity2.origin.z += 7.5f;
      identity2.rotation.ApplyScaleLocal(10f);
      MatrixFrame frame2 = identity2;
      gameEntity2.SetFrame(ref frame2);
      gameEntity2.SetVisibilityExcludeParents(true);
      gameEntity2.SetAlpha(1f);
    }

    private void HideDeploymentBanners(DeploymentPoint deploymentPoint, bool isRemoving = false)
    {
      (GameEntity, GameEntity) tuple;
      this._deploymentBanners.TryGetValue(deploymentPoint, out tuple);
      if (!((NativeObject) tuple.Item1 != (NativeObject) null) || !((NativeObject) tuple.Item2 != (NativeObject) null))
        return;
      if (isRemoving)
      {
        tuple.Item1.Remove(104);
        tuple.Item2.Remove(105);
      }
      else
      {
        tuple.Item1.SetVisibilityExcludeParents(false);
        tuple.Item2.SetVisibilityExcludeParents(false);
      }
    }

    private (GameEntity, GameEntity) CreateBanners(DeploymentPoint deploymentPoint)
    {
      GameEntity bannerEntity1 = this.CreateBannerEntity(false);
      bannerEntity1.SetVisibilityExcludeParents(false);
      GameEntity bannerEntity2 = this.CreateBannerEntity(true);
      bannerEntity2.SetVisibilityExcludeParents(false);
      (GameEntity, GameEntity) banners = (bannerEntity1, bannerEntity2);
      this._deploymentBanners.Add(deploymentPoint, banners);
      return banners;
    }

    private GameEntity CreateBannerEntity(bool isTargetEntity)
    {
      GameEntity empty = GameEntity.CreateEmpty(Mission.Current.Scene);
      empty.EntityFlags |= EntityFlags.NoOcclusionCulling;
      uint num1 = 4278190080;
      uint num2 = isTargetEntity ? 2131100887U : 2141323264U;
      empty.AddMultiMesh(MetaMesh.GetCopy("billboard_unit_mesh"));
      empty.GetFirstMesh().Color = uint.MaxValue;
      Material copy = Material.GetFromResource("formation_icon").CreateCopy();
      if (isTargetEntity)
      {
        Texture fromResource = Texture.GetFromResource("plain_yellow");
        copy.SetTexture(Material.MBTextureType.DiffuseMap2, fromResource);
      }
      else
      {
        Texture fromResource = Texture.GetFromResource("plain_blue");
        copy.SetTexture(Material.MBTextureType.DiffuseMap2, fromResource);
      }
      empty.GetFirstMesh().SetMaterial(copy);
      empty.GetFirstMesh().Color = num2;
      empty.GetFirstMesh().Color2 = num1;
      empty.GetFirstMesh().SetVectorArgument(0.0f, 1f, 0.0f, 1f);
      return empty;
    }

    private void ShowPath(DeploymentPoint deploymentPoint)
    {
      (deploymentPoint.GetWeaponsUnder().FirstOrDefault<SynchedMissionObject>((Func<SynchedMissionObject, bool>) (wu => wu is IMoveableSiegeWeapon)) as IMoveableSiegeWeapon).HighlightPath();
    }

    private void SetGhostVisibility(DeploymentPoint deploymentPoint, bool isVisible)
    {
    }

    private void SetDeploymentTargetContourState(
      DeploymentPoint deploymentPoint,
      bool isHighlighted)
    {
      switch (deploymentPoint.GetDeploymentPointState())
      {
        case DeploymentPoint.DeploymentPointState.SiegeLadder:
          using (List<SiegeLadder>.Enumerator enumerator = deploymentPoint.GetAssociatedSiegeLadders().GetEnumerator())
          {
            while (enumerator.MoveNext())
            {
              SiegeLadder current = enumerator.Current;
              if (isHighlighted)
                current.GameEntity.SetContourColor(new uint?(4289622555U));
              else
                current.GameEntity.SetContourColor(new uint?());
            }
            break;
          }
        case DeploymentPoint.DeploymentPointState.Breach:
          if (isHighlighted)
          {
            deploymentPoint.AssociatedWallSegment.GameEntity.SetContourColor(new uint?(4289622555U));
            break;
          }
          deploymentPoint.AssociatedWallSegment.GameEntity.SetContourColor(new uint?());
          break;
      }
    }

    private void SetLaddersUpState(DeploymentPoint deploymentPoint, bool isRaised)
    {
      foreach (SiegeLadder associatedSiegeLadder in deploymentPoint.GetAssociatedSiegeLadders())
        associatedSiegeLadder.SetUpStateVisibility(isRaised);
    }

    private void SetLightState(DeploymentPoint deploymentPoint, bool isVisible)
    {
      GameEntity gameEntity;
      this._deploymentLights.TryGetValue(deploymentPoint, out gameEntity);
      if ((NativeObject) gameEntity != (NativeObject) null)
      {
        gameEntity.SetVisibilityExcludeParents(isVisible);
      }
      else
      {
        if (!isVisible)
          return;
        this.CreateLight(deploymentPoint);
      }
    }

    private void CreateLight(DeploymentPoint deploymentPoint)
    {
      MatrixFrame identity = MatrixFrame.Identity with
      {
        origin = deploymentPoint.DeploymentTargetPosition + new Vec3(z: deploymentPoint.GetDeploymentPointType() == DeploymentPoint.DeploymentPointType.TowerLadder ? 10f : 3f)
      };
      identity.rotation.RotateAboutSide(1.57079637f);
      identity.Scale(new Vec3(5f, 5f, 5f));
      GameEntity gameEntity = GameEntity.Instantiate(Mission.Current.Scene, "aserai_keep_interior_a_light_shaft_a", identity);
      this._deploymentLights.Add(deploymentPoint, gameEntity);
    }

    public enum DeploymentVisualizationPreference
    {
      ShowUndeployed = 1,
      Line = 2,
      Arc = 4,
      Banner = 8,
      Path = 16, // 0x00000010
      Ghost = 32, // 0x00000020
      Contour = 64, // 0x00000040
      LiftLadders = 128, // 0x00000080
      Light = 256, // 0x00000100
      AllEnabled = 1023, // 0x000003FF
    }
  }
}
